


/**
 * Class to construct and deconstruct data messages.
 * @author Karsten
 *
 */
public class DataMessage 
{
	private final static int TYPE_INDEX = 0;
	private final static int LEN_INDEX = 1;
	private final static int ID_INDEX = 2;
	private final static int VALUE_INDEX = 3;
	private final static int TEXT_BEGIN_INDEX = VALUE_INDEX;
	
	public final static byte TYPE_TEXT = 0x01;
	public final static byte TYPE_COMMAND = 0x02;
	public final static byte TYPE_SETTING = 0x03;
	
	private byte[] _data;
	
	/**
     * Creates a message from RAW bytes.
     * @param data Bytes from which to create message.
     */
	public DataMessage(byte[] data)
	{
		_data = data;	
	}

	/**
     * Create a text message
     * @param id Identifier for the string.
     * @param text The message text.
     */
	public DataMessage(byte id, String text)
	{
		byte str_len =(byte)text.length();
		_data = new byte[str_len + VALUE_INDEX];
		_data[TYPE_INDEX] = TYPE_TEXT;
		_data[LEN_INDEX] = (byte)(str_len + 1);
		_data[ID_INDEX] = id;
		
		for(int i = 0 ; i < str_len ; i++)
		{
			_data[i + VALUE_INDEX] = (byte)text.charAt(i);
		}
	}
	
	/**
     * Creates a command message.
     * @param id Identifier for the command.
     */
	public DataMessage(byte id)
	{
		_data = new byte[ID_INDEX];
		_data[TYPE_INDEX] = TYPE_COMMAND;
		_data[LEN_INDEX] = 1;
		_data[ID_INDEX] = id;
	}

	/**
     * Create a setting message.
     * @param id Identifier for the setting.
     * @param value The new value for the setting.
     */
	public DataMessage(byte id, byte value)
	{
		_data = new byte[VALUE_INDEX];
		_data[TYPE_INDEX] = TYPE_SETTING;
		_data[LEN_INDEX] = 2;
		_data[ID_INDEX] = id;
		_data[VALUE_INDEX] = value;
	}
	
	/**
     * Method to check if message is valid
     * @return The number of values returned.
     */
	public boolean isValid()
	{
		boolean valid = _data != null;
		if(valid)
		{
			// Check length
			valid = (_data.length == _data[LEN_INDEX] + LEN_INDEX + 1);
		}
		
		return valid;
	}
	
	/**
     * Get access to RAW message bytes.
     * @return Byte array.
     */
	public byte[] getBytes()
	{
		return _data;
	}
	
	/**
     * Get size of RAW message bytes.
     * @return Byte size of the message
     */
	public int getSize()
	{
		return _data.length;
	}
	
	/**
     * Get the type of the message.
     * Use this to decide which get* method to use.
     * @return The message type.
     */
	public int getType()
	{
		if(isValid())
		{
			return _data[TYPE_INDEX];
		}
		else
		{
			return -1;
		}
	}
	
	 // @return 0 if ok <> 0 otherwise
	 
	
	/**
     * Get the identifier of the message.
     * All message types have an identifier.
     * @return id if isValid() else -1
     */
	public int getIdentifier()
	{
		if( isValid() )
		{
			return _data[ID_INDEX];
		}
		else
		{
			return -1;
		}
	}
	
	/**
     * Get the message text.
     * @return text if isValid() AND getType() == TYPE_TEXT else null
     */
	public String getText()
	{
		if(isValid() && _data[TYPE_INDEX] == TYPE_TEXT)
		{
			int str_size = _data[LEN_INDEX] - 1;
			String str = "";
			
			for(int i = 0 ; i < str_size ; i++)
			{
				str += (char)_data[i + VALUE_INDEX];
			}
			
			return str;
		}
		else
		{
			return null;
		}
	}

	/**
     * Get the message value.
     * @return value if isValid() AND getType() == TYPE_SETTING else -1
     */
	public int getValue()
	{
		if(isValid() && getType() == TYPE_SETTING)
		{
			return _data[VALUE_INDEX];
		}
		else
		{
			return -1;
		}
	}

}
